using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
//using System.Net.Mail;
using System.Web.Mail;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SQLite;
using System.Media;

namespace website_monitor
{
    /// <summary>
    /// 测试版本
    /// </summary>
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
            StartPosition = FormStartPosition.CenterScreen;
        }
        public int secrs = 0;//用于timeout超时
        public Thread th;//全局thread 线程
        public System.Timers.Timer ts = new System.Timers.Timer();//全局timer 线程
        public int i = 0;
        public int b = 0;//用于统计错误
        public int secrv = 0;
        public int m = 0;//用于控制临界值使用
        private void timer1_Tick(object sender, EventArgs e)
        {
            toolStripStatusLabel3.Text = System.DateTime.Now.ToString("F");//F 显示完整的日期及时间
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            toolStripStatusLabel2.Text = "0";
            //默认停止不进行显示
            button2.Enabled = false;
            
        }

        private void toolStripStatusLabel3_Click(object sender, EventArgs e)
        {
            toolStripStatusLabel3.Text = System.DateTime.Now.ToString("F");//F 显示完整的日期及时间
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            //点击开始后 开始按钮不可用 ，唯有线程停止 或 手动停止后方可进行使用
            button1.Enabled = false;
            button2.Enabled = true;
            this.timer2.Enabled = true;
            this.timer2.Interval = 100;
            this.timer2.Start();
            if (textBox1.Text == string.Empty)
            {
                LogError("监测时间：" + DateTime.Now + "   ------   " + "监测数据不能为空" + "\r\n");
                timer1.Stop();
                button1.Enabled = true;
                button2.Enabled = false;
                return;
            }
            LogError("监测时间：" + DateTime.Now + "   ------   " + "正在创建监测任务" + "\r\n");
            //先创建一个请求判断地址能进行访问
            string url = textBox1.Text;
            try
            {
                //发起请求
                HttpWebRequest res = (HttpWebRequest)WebRequest.Create(url);
                res.AllowAutoRedirect = false;
                res.KeepAlive = false;
                HttpWebResponse response = (HttpWebResponse)res.GetResponse();
                var v = response.StatusCode;//初始化状态
                if (v == HttpStatusCode.OK)
                {
                    //进行日志记录
                    AppLog.WriteInfo("发现时间：" + DateTime.Now, true);
                    //AppLog.WriteInfo(richTextBox1.Text += "发现时间：" + DateTime.Now + "\r\n", true);
                    //进行打印输出
                    LogMessage("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产可用" + "\r\n");
                    //Console.WriteLine(richTextBox1.Text += DateTime.Now + "   ------   " + "网站资产可用" + "\r\n");
                    //创建一个线程执行
                    th = new Thread(WebMoitor);
                    th.IsBackground = false;
                    th.Start();
                    LogMessage("监测时间：" + DateTime.Now + "   ------   " + "监测线程创建成功" + "\r\n");
                }
                else
                {
                    //进行日志记录
                    AppLog.WriteError("发现时间：" + DateTime.Now, true);
                    //进行打印输出  循环绑定到定时器上 执行N次
                    LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + "\r\n");
                    return;
                    //预警提示
                }
            }
            catch (Exception ex)
            {
                //打印错误日志
                AppLog.WriteWarn("发现时间：" + DateTime.Now, true);
                //实时输出错误
                AppLog.WriteWarn("错误提示：" + ex, true);
                //Console.WriteLine(richTextBox1.Text += DateTime.Now + "   ------   " + "网站资产无法访问" + "\r\n" + ex + "\r\n");
                LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + "\r\n");
                button1.Enabled = true;
                button2.Enabled = false;
                return;
            }
        }
/// <summary>
/// 监测核心
/// </summary>
        public void WebMoitor()
        {
            //System.Timers.Timer timer = new System.Timers.Timer();
            int swgf = Convert.ToInt32(textBox2.Text);//获取int类型格式
            secrv = swgf * 1000;//把获取到的结果拿来乘以 1000 也就是把秒 转 毫秒
            ts.Interval = Convert.ToInt32(secrv);
            ts.Enabled = true;
            ts.AutoReset = true;//一直执行 如果关闭就没有办法进行一直执行
            ts.Elapsed += new System.Timers.ElapsedEventHandler(time_elas);
            ts.Start();
        }
        public void time_elas(object sender,System.Timers.ElapsedEventArgs e)
        {
            string url = textBox1.Text;
            try
            {
                //增加一个请求延迟
                System.Threading.Thread.Sleep(100);
                //发起请求
                HttpWebRequest res = (HttpWebRequest)WebRequest.Create(url);
                res.Method = "GET";

                //下面这种方式反了
                int swgf = Convert.ToInt32(textBox3.Text);//获取int类型格式
                secrv = swgf * 1000;//把获取到的结果拿来乘以 1000 也就是把秒 转 毫秒
                res.Timeout = Convert.ToInt32(secrv.ToString());//隐式转换为int类型

                HttpWebResponse response = (HttpWebResponse)res.GetResponse();
                var v = response.StatusCode;//初始化状态
                if (v == HttpStatusCode.OK)
                {
                    //进行日志记录
                    AppLog.WriteInfo("发现时间：" + DateTime.Now, true);
                    //AppLog.WriteInfo(richTextBox1.Text += "发现时间：" + DateTime.Now + "\r\n", true);
                    //进行打印输出
                    LogMessage("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产可用" + "\r\n");
                    //Console.WriteLine(richTextBox1.Text += DateTime.Now + "   ------   " + "网站资产可用" + "\r\n");
                    //记录次数
                    i++;
                    toolStripStatusLabel5.Text = i.ToString();
                    //预警记录 不进行提示，这个地方往sqlite数据库进行存放数据，单独拿出来 + 1
                    try
                    {
                        // 读取数据的方法
                        string path = "data source=Sec-montior.db";
                        SQLiteConnection dataConn = new SQLiteConnection(path);
                        dataConn.Open();
                        if (dataConn.State == ConnectionState.Open)
                        {
                            //如果数据库能打开的情况下 把数据存入到数据库中
                            string sql = "INSERT INTO sec_montior (title, url, time) VALUES('{0}', '{1}', '{2}')";
                            sql = string.Format(sql, "资产监测正常",textBox1.Text,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                            SQLiteCommand command = new SQLiteCommand(sql, dataConn);
                            command.ExecuteNonQuery();
                            SQLiteDataAdapter mAdapt = new SQLiteDataAdapter(command);
                            var ss = mAdapt.ToString();
                            //判断是否进行执行 如果执行之后就进行打印
                            if (ss.Length != 1)
                            {
                                LogWarning("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "监测数据已保存" + "\r\n");
                            }
                        }
                        else
                        {
                            //进行日志记录
                            AppLog.WriteError("发现时间：" + DateTime.Now, true);
                            //进行打印输出  循环绑定到定时器上 执行N次
                            LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + "\r\n");
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        //记录错误日志 这个日志不会同步到数据库 经过测试 上方因为是实时往数据库中进行存放的数据 在对设备性能上面有一定的要求
                        AppLog.WriteError("错误时间" + DateTime.Now + "\r\n" + ex,true);
                        Console.WriteLine("错误时间" + DateTime.Now + "\r\n" + ex);
                    }
                    //记录往数据库写入结果完成
                }
                else
                {
                    //进行日志记录
                    AppLog.WriteError("发现时间：" + DateTime.Now, true);
                    //进行打印输出  循环绑定到定时器上 执行N次
                    LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + "\r\n");
                    //预警提示 第一种是无法访问的状态下，并非连接超时导致的情况
                    SoundPlayer sp;
                    try
                    {
                        sp = new SoundPlayer();
                        sp.SoundLocation = "./error404.wav";
                        sp.PlayLooping();//循环播放
                    }
                    catch (Exception ex)
                    {
                        LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + ex + "\r\n");
                        return;
                    }
                    //创建一个thread 线程来进行通知，有个问题是实时通知的情况下，会导致邮箱被限制发送邮件，否则会形成邮箱轰炸
                    Thread tk = new Thread(MailSender);
                    tk.Start();
                    //统计m的超时次数 当超时此处达到多少次之后 不进行预警，并清空计算从新进行计算
                    if (toolStripStatusLabel9.Text == textBox4.Text)//判断如果失败错误次数达到5之后，首先第一条是终止预警线程
                    {
                        tk.Abort();//终止发送预警线程
                        toolStripStatusLabel9.Text = "0";
                        m = 0;//把m值进行归零
                        m++;//从新计算
                        toolStripStatusLabel9.Text = m.ToString();//从新进行统计 预警信息已达临界值，已终止邮箱预警
                        LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "预警信息已达临界值，已终止邮箱预警" + "\r\n");
                    }
                }
            }
            catch (Exception ex)
            {
                //打印错误日志
                AppLog.WriteWarn("发现时间：" + DateTime.Now, true);
                //实时输出错误
                AppLog.WriteWarn("错误提示：" + ex, true);
                //打印错误信息
                Console.WriteLine(richTextBox1.Text += "发现时间：" + DateTime.Now + "   ------   " + "\r\n" + ex + "\r\n");
                b++;
                m++;
                toolStripStatusLabel7.Text = b.ToString();
                toolStripStatusLabel9.Text = m.ToString();
                //超时等情况下 播放提示音
                SoundPlayer sp;
                try
                {
                    sp = new SoundPlayer();
                    sp.SoundLocation = "./error404.wav";
                    sp.PlayLooping();//循环播放
                }
                catch (Exception exs)
                {
                    LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "网站资产无法访问" + "\r\n");
                    return;
                } 
                //创建一个thread 线程来进行通知，有个问题是实时通知的情况下，会导致邮箱被限制发送邮件，否则会形成邮箱轰炸
                Thread tk = new Thread(MailSender);
                tk.Start();
                //统计m的超时次数 当超时此处达到多少次之后 不进行预警，并清空计算从新进行计算
                if (toolStripStatusLabel9.Text == textBox4.Text)//判断如果失败错误次数达到5之后，首先第一条是终止预警线程
                {
                    tk.Abort();//终止发送预警线程
                    toolStripStatusLabel9.Text = "0";
                    m = 0;//把m值进行归零
                    m++;//从新计算
                    toolStripStatusLabel9.Text = m.ToString();//从新进行统计
                    LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "预警信息已达临界值，已终止邮箱预警" + "\r\n");
                }
            }
        }
        public void MailSender()
        {
            Email.MailSend("tangxuan@cqdhxk.com", "监测可用性预警：", "<b>监测资产：</b>" + textBox1.Text + "<br>" + "<b>监测状态：</b>" + "资产监测超时" + "<br>" + "<b>监测时间：</b>" + DateTime.Now + "<br>" + "<b>技术支持：</b>" + "Sec-scan安全" + "<br>" + "<b>解决方案：</b>" + "登录系统进行处理或访问https://sec-scan.srcbug.net进行反馈",//收件人账号 、标题 、内容
                        "huaxiahonker@163.com",//发件人账号
                        "ZHFWUMQKEKFWTTEN",//发件人密码或授权码
                        "smtp.163.com",//发件人服务器
                        BccAddressList: new List<string>() { "huaxiahonker@163.com" });//抄送密送  可不进行填写
                                                                                       //执行成功后给一个反馈
            Console.WriteLine(richTextBox1.Text += DateTime.Now + "   ------   " + "已发送邮箱通知" + "\r\n");
        }
        private void button2_Click(object sender, EventArgs e)
        {
            if (th != null && th.IsAlive)
            {
                th.Abort();
                this.timer2.Enabled = false;
                this.timer2.Stop();
                ts.Enabled = false;
                button1.Enabled = true;
                button2.Enabled = false;
                toolStripStatusLabel2.Text = "0";
                LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "监测线程已终止" + "\r\n");
                return;
            }
            //timer 线程终止的方式 该线程的方式主要来实现对资产进行监测
            ts.Enabled = false;
            this.timer2.Enabled = false;
            this.timer2.Stop();
            button1.Enabled = true;
            button2.Enabled = false;
            toolStripStatusLabel2.Text = "0";
            LogError("监测时间：" + DateTime.Now + "   ------   " + "监测资产" + textBox1.Text + "   ------   " + "监测状态：" + "监测线程已终止" + "\r\n");
            return;
        }

        private void timer3_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //创建一个需要执行的线程 或 执行的方法
        }
        /// <summary>
        /// 对输出颜色进行封装 rictextbox1
        /// </summary>
        /// <param name="color"></param>
        /// <param name="text"></param>
        public delegate void LogAppendDelegate(Color color, string text);
        public void LogAppend(Color color, string text)
        {
            //richTextBox1.AppendText("\r\n");
            richTextBox1.SelectionColor = color;
            richTextBox1.AppendText(text);
        }
        /// red
        public void LogError(string text)
        {
            LogAppendDelegate la = new LogAppendDelegate(LogAppend);
            richTextBox1.Invoke(la, Color.Red, text);
        }
        /// 警告
        public void LogWarning(string text)
        {
            LogAppendDelegate la = new LogAppendDelegate(LogAppend);
            richTextBox1.Invoke(la, Color.Violet, text);
        }
        /// 绿色
        public void LogMessage(string text)
        {
            LogAppendDelegate la = new LogAppendDelegate(LogAppend);
            richTextBox1.Invoke(la, Color.Green, text);
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            //获取线程数
            Process myProcess = Process.GetCurrentProcess();//获取该进程
            ProcessThreadCollection PTC = myProcess.Threads;//获取其关联的线程，包括主线程
            int num = PTC.Count;//获取线程数量
            toolStripStatusLabel2.Text = num.ToString();
            
        }
        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            //设置richtextbox 默认显示最新的一条数据
            if (richTextBox1.Text.Length > 0)
            {
                richTextBox1.SelectionStart = richTextBox1.Text.Length;
                richTextBox1.ScrollToCaret();
            }
        }
        public void ErrorEmail()
        {
            //
        }

        private void 创建监测项目ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            form1.StartPosition = FormStartPosition.CenterScreen;
            form1.Show();
        }

        private void 退出系统ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void 监测项目报告ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Report report = new Report();
            report.StartPosition = FormStartPosition.CenterScreen;
            report.ShowDialog();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (th != null && th.IsAlive)
            {
                DialogResult Result = MessageBox.Show("请终止扫描线程后进行关闭，强制关闭程序将引发错误", "操作警告", MessageBoxButtons.OKCancel);
                if (Result == DialogResult.Cancel)
                {
                    e.Cancel = true;
                }
            }
        }
    }
}
